import { isObject, hasChanged, isArray } from '../utils';
import { track, trigger } from './effect';

const reactiveMap = new WeakMap();

export function reactive(target) {
  // 如果不是一个对象, 直接return
  if (!isObject(target)) {
    return target;
  }
  // 如果target是代理对象
  // const a = reactive(obj) 
  // reactive(a)
  if (isReactive(target)) {
    return target;
  }
  // 如果之前代理过这个对象
  // const obj = {}
  // const a = reactive(obj), 
  // const b = reactive(obj)
  if (reactiveMap.has(target)) {
    return reactiveMap.get(target);
  }
  const proxy = new Proxy(target, {
    get(target, key, receiver) {
      if (key === '__isReactive') {
        return true; // 用于判断一个对象是否是代理对象, isReactive()用
      }
      track(target, key);// 搜集副作用
      const res = Reflect.get(target, key, receiver);
      // 深度代理
      // 调用的时候才代理, 懒代理, vue3采用懒代理
      // vue2一上来直接递归, 把所有的属性代理一遍
      return isObject(res) ? reactive(res) : res;
    },
    set(target, key, value, receiver) {
      const oldValue = target[key];
      const oldLength = target.length;
      const res = Reflect.set(target, key, value, receiver);
      if (hasChanged(value, oldValue)) {
        trigger(target, key); // 触发副作用
        if (isArray(target) && target.length !== oldLength) {
          trigger(target, 'length');// arr.push 会修改length属性
        }
      }
      return res;
    },
  });
  reactiveMap.set(target, proxy);
  return proxy;
}
// 判断一个对象是否已经被代理过
export function isReactive(target) {
  return !!(target && target.__isReactive);
}
